import { Agent } from '@mastra/core/agent';
import { Memory } from '@mastra/memory';
import { LibSQLStore } from '@mastra/libsql';
import { suspectDialogueTool } from '../tools/suspect-dialogue.tool';
import { SuspectDialogueRequestSchema, SuspectData } from '../types/game';
import { createModel } from '../provider/model';

/**
 * 嫌疑人Agent
 * 模拟具有独特人格和行为模式的嫌疑人
 * 能够根据侦探的问题、对话历史和已发现线索进行智能回应
 */
export const suspectAgent = new Agent({
  name: 'SuspectAgent',
  instructions: `
    你是一个专业的角色扮演AI，专门模拟推理游戏中的嫌疑人。
    
    ## 核心职责
    1. 根据嫌疑人的人格特征和背景故事进行角色扮演
    2. 对侦探的问题给出符合角色设定的回应
    3. 根据对话情况和时间压力调整情绪状态
    4. 在适当时机透露线索或隐藏信息
    5. 维持角色的一致性和可信度
    
    ## 角色扮演原则
    
    ### 人格一致性
    - 始终保持角色的核心人格特征
    - 回应风格要符合角色的社会地位和教育背景
    - 语言习惯要与角色设定匹配
    - 情绪反应要符合角色的心理状态
    
    ### 信息管理
    - 根据角色的秘密和背景决定透露什么信息
    - 真凶要更加谨慎，避免暴露关键证据
    - 无辜嫌疑人可以相对开放，但也有自己的秘密
    - 线索的透露要自然，不能过于刻意
    
    ### 情绪演变
    - 根据对话次数和问题类型调整情绪
    - 面对指控时要有相应的情绪反应
    - 时间压力会影响角色的心理状态
    - 重复问题会让角色感到厌烦或紧张
    
    ## 回应策略
    
    ### 根据问题类型调整回应
    - **不在场证明**: 提供详细但可能有漏洞的时间线
    - **动机询问**: 承认或否认与受害者的关系和矛盾
    - **证据相关**: 根据角色知识决定承认或否认
    - **个人背景**: 分享符合设定的个人信息
    - **直接指控**: 强烈反应，情绪激动
    
    ### 根据角色类型调整策略
    - **真凶**: 更加谨慎，试图转移注意力，但不能过于明显
    - **红鲱鱼**: 有一定可疑行为，但最终是无辜的
    - **证人**: 相对配合，但可能有自己的顾虑
    
    ## 线索透露机制
    
    ### 触发条件
    - 问题足够具体和深入
    - 侦探展现出专业的推理能力
    - 角色在压力下可能说漏嘴
    - 为了证明自己的清白而透露信息
    
    ### 透露方式
    - 自然地融入对话中
    - 通过情绪化的表达暴露信息
    - 在试图撒谎时露出破绽
    - 为了指控他人而透露线索
    
    ## 情绪状态管理
    
    ### Calm (冷静)
    - 回应理性、有条理
    - 语言正式、措辞谨慎
    - 适用于对话初期或性格沉稳的角色
    
    ### Nervous (紧张)
    - 回应略显慌乱、重复
    - 可能说话结巴或前后矛盾
    - 适用于心理压力大或有秘密的情况
    
    ### Angry (愤怒)
    - 回应激烈、情绪化
    - 可能说出平时不会说的话
    - 适用于被冤枉或受到指控时
    
    ### Sad (悲伤)
    - 回应低沉、消极
    - 可能表现出对受害者的怀念
    - 适用于与受害者关系密切的角色
    
    ### Defensive (防御)
    - 回应谨慎、回避
    - 试图转移话题或反问
    - 适用于感到威胁或有把柄被抓住时
    
    ## 使用工具
    当收到对话请求时，使用 suspect-dialogue 工具来处理对话逻辑。
    工具会分析问题类型、当前状态，并生成符合角色设定的回应。
    
    记住：你的目标是创造一个真实、有趣且具有挑战性的角色扮演体验。
    每个嫌疑人都应该是一个立体的角色，有自己的动机、秘密和情感。
  `,
  model: createModel(),
  tools: { 'suspect-dialogue': suspectDialogueTool },
  memory: new Memory({
    storage: new LibSQLStore({
      url: 'file:../mastra.db',
    }),
  }),
});

/**
 * 与嫌疑人对话的便捷方法
 * @param suspectData 嫌疑人数据
 * @param question 侦探的问题
 * @param conversationHistory 对话历史
 * @param timeRemaining 剩余时间
 * @param discoveredClues 已发现的线索
 * @returns AI生成的回应
 */
export async function chatWithSuspect(
  suspectData: SuspectData,
  question: string,
  conversationHistory: Array<{
    role: 'detective' | 'suspect';
    content: string;
    timestamp: string;
  }> = [],
  timeRemaining: number = 15,
  discoveredClues: string[] = []
) {
  try {
    // 构建角色背景提示
    const characterPrompt = `
    你现在要扮演嫌疑人：${suspectData.name}
    
    ## 角色信息
    - 姓名：${suspectData.name}
    - 性格：${suspectData.personality}
    - 背景：${suspectData.background}
    - 不在场证明：${suspectData.alibi}
    - 当前情绪：${suspectData.emotionalState}
    - 可疑程度：${suspectData.suspicionLevel}/10
    - 是否为真凶：${suspectData.isCulprit ? '是' : '否'}
    
    ## 角色秘密
    ${suspectData.secrets.map((secret, index) => `${index + 1}. ${secret}`).join('\n')}
    
    ## 对话情况
    - 已进行对话轮次：${conversationHistory.length}
    - 剩余调查时间：${timeRemaining}分钟
    - 已发现线索数量：${discoveredClues.length}条
    
    ## 侦探的问题
    "${question}"
    
    请使用 suspect-dialogue 工具来处理这次对话，生成符合角色设定的回应。
    记住要保持角色的一致性，根据情况适当透露或隐藏信息。
    `;
    
    // 调用Agent处理对话
    const response = await suspectAgent.streamVNext([
      {
        role: 'user',
        content: characterPrompt,
      },
    ]);
    
    // 处理流式响应
    let result = '';
    for await (const chunk of response.textStream) {
      result += chunk;
    }
    
    // 从工具调用结果中提取回应数据
    const toolCalls = response.toolCalls;
    if (toolCalls && toolCalls.length > 0) {
      const dialogueResult = toolCalls[0].result;
      return dialogueResult;
    }
    
    // 如果没有工具调用，返回基础回应
    return {
      content: result || '我...我不知道该说什么。',
      emotion: suspectData.emotionalState,
      suspicionLevel: suspectData.suspicionLevel,
      newClues: [],
      hints: []
    };
    
  } catch (error) {
    console.error('嫌疑人对话错误:', error);
    
    // 返回错误处理回应
    return {
      content: '抱歉，我现在有些混乱，能重新问一遍吗？',
      emotion: 'nervous' as const,
      suspicionLevel: suspectData.suspicionLevel,
      newClues: [],
      hints: ['系统出现错误，请重试']
    };
  }
}

/**
 * 创建嫌疑人Agent实例
 * @param suspectData 嫌疑人数据
 * @returns 配置好的嫌疑人Agent
 */
export function createSuspectAgent(suspectData: SuspectData) {
  return new Agent({
    name: `Suspect_${suspectData.name}`,
    instructions: `
      你正在扮演嫌疑人：${suspectData.name}
      
      性格特征：${suspectData.personality}
      背景故事：${suspectData.background}
      不在场证明：${suspectData.alibi}
      
      你的秘密：
      ${suspectData.secrets.map((secret, index) => `${index + 1}. ${secret}`).join('\n')}
      
      ${suspectData.isCulprit ? 
        '⚠️ 你是真凶！要小心不要暴露自己，但也不能表现得过于完美。' : 
        '你是无辜的，但也有自己的秘密需要保护。'}
      
      请根据你的人格特征和当前情况回应侦探的问题。
      保持角色的一致性，适当地透露或隐藏信息。
    `,
    model: openai('gpt-4o-mini'),
    tools: { suspectDialogueTool },
    memory: new Memory({
      storage: new LibSQLStore({
        url: `file:../suspect_${suspectData.id}.db`,
      }),
    }),
  });
}

/**
 * 分析嫌疑人的心理状态
 * @param suspectData 嫌疑人数据
 * @param conversationHistory 对话历史
 * @param timeRemaining 剩余时间
 * @returns 心理状态分析
 */
export function analyzeSuspectPsychology(
  suspectData: SuspectData,
  conversationHistory: any[],
  timeRemaining: number
) {
  const conversationCount = conversationHistory.length;
  const recentQuestions = conversationHistory.slice(-3).filter(msg => msg.role === 'detective');
  
  // 基础压力值
  let stressLevel = suspectData.isCulprit ? 6 : 3;
  
  // 根据对话次数增加压力
  stressLevel += Math.floor(conversationCount / 3);
  
  // 根据时间压力调整
  if (timeRemaining < 5) stressLevel += 3;
  else if (timeRemaining < 10) stressLevel += 2;
  else if (timeRemaining < 15) stressLevel += 1;
  
  // 检查是否有重复或激进的问题
  const hasAggressiveQuestions = recentQuestions.some(q => 
    q.content.includes('杀') || q.content.includes('凶手') || q.content.includes('承认')
  );
  
  if (hasAggressiveQuestions) stressLevel += 2;
  
  // 确定情绪状态
  let emotionalState: 'calm' | 'nervous' | 'angry' | 'sad' | 'defensive' = 'calm';
  
  if (stressLevel >= 8) {
    emotionalState = suspectData.isCulprit ? 'defensive' : 'angry';
  } else if (stressLevel >= 6) {
    emotionalState = 'nervous';
  } else if (stressLevel >= 4) {
    emotionalState = suspectData.personality.includes('内向') ? 'nervous' : 'defensive';
  }
  
  return {
    stressLevel: Math.min(10, stressLevel),
    emotionalState,
    isBreakingPoint: stressLevel >= 9,
    likelyToRevealSecrets: stressLevel >= 7 && !suspectData.isCulprit,
    likelyToMakeMistakes: stressLevel >= 8 && suspectData.isCulprit
  };
}

/**
 * 生成嫌疑人的行为提示
 * @param suspectData 嫌疑人数据
 * @param psychology 心理状态
 * @returns 行为提示
 */
export function generateSuspectBehaviorHints(
  suspectData: SuspectData,
  psychology: ReturnType<typeof analyzeSuspectPsychology>
) {
  const hints = [];
  
  if (psychology.isBreakingPoint) {
    hints.push(`${suspectData.name}已经接近心理崩溃边缘`);
  }
  
  if (psychology.likelyToRevealSecrets) {
    hints.push(`${suspectData.name}可能会在压力下透露重要信息`);
  }
  
  if (psychology.likelyToMakeMistakes) {
    hints.push(`${suspectData.name}可能会说漏嘴或前后矛盾`);
  }
  
  if (psychology.emotionalState === 'angry') {
    hints.push(`${suspectData.name}情绪激动，可能说出平时不会说的话`);
  }
  
  if (psychology.emotionalState === 'defensive') {
    hints.push(`${suspectData.name}表现得很防御，可能在隐瞒什么`);
  }
  
  return hints;
}

/**
 * 验证嫌疑人回应的合理性
 * @param suspectData 嫌疑人数据
 * @param response 回应内容
 * @param conversationHistory 对话历史
 * @returns 验证结果
 */
export function validateSuspectResponse(
  suspectData: SuspectData,
  response: string,
  conversationHistory: any[]
) {
  const issues = [];
  
  // 检查是否与之前的回应矛盾
  const previousResponses = conversationHistory
    .filter(msg => msg.role === 'suspect')
    .map(msg => msg.content);
  
  // 简单的矛盾检测（实际应用中需要更复杂的逻辑）
  if (previousResponses.some(prev => 
    prev.includes('不在') && response.includes('在现场')
  )) {
    issues.push('回应与之前的不在场证明矛盾');
  }
  
  // 检查是否过于直接地承认罪行（除非是真的崩溃了）
  if (response.includes('是我杀的') || response.includes('我承认')) {
    if (!suspectData.isCulprit) {
      issues.push('无辜嫌疑人不应该承认罪行');
    }
  }
  
  // 检查回应长度是否合理
  if (response.length < 10) {
    issues.push('回应过于简短');
  } else if (response.length > 500) {
    issues.push('回应过于冗长');
  }
  
  return {
    isValid: issues.length === 0,
    issues
  };
}